백그라운드에서의 setInterval
도서관 자리를 1초마다 조회하는 리액트앱을 만들어서 맥북에서 백그라운드로 동작시켰다. 하지만 어느순간 주기가 1분으로 늘어나는 것을 발견했다.
그래서 이 원인을 찾아보자!
범인은 바로 너!
원인 분석
먼저 setInterval의 작동의 문제라고 생각했기 때문에 관련 문서를 좀 뒤져봤따.
mdn web docs - setInterval
문서 내용 중 setInterval시 delay가 발생할 수 있는 여러가지 경우를 알려준다.
- timeouts in inactive tabs
- late timeouts
- deferral of timeouts during pageload
timeouts in inactive tabs 항목을 잘 살펴보자
Timeouts in inactive tabs
To reduce the load (and associated battery usage) from background tabs, browsers will enforce a minimum timeout delay in inactive tabs. It may also be waived if a page is playing sound using a Web Audio API
AudioContext
.
The specifics of this are browser-dependent:
- Firefox Desktop and Chrome both have a minimum timeout of 1 second for inactive tabs.
- Firefox for Android has a minimum timeout of 15 minutes for inactive tabs and may unload them entirely.
- Firefox does not throttle inactive tabs if the tab contains an
AudioContext
.
요약하자면, 브라우저는 백그라운드의 리소스를 줄이기 위해 활성화되지 않은 탭에서의 minimum timeout을 1초로 정하고 있다고 한다.
firefox와 chrome이 언급되고 있어서 얼른 electron 의 기반을 찾아봤는데, V8 ENGINE을 사용중이라고 한다.ㅜ
is Electron uses v8?
chrome 문서에서 좀 더 자세한 정책을 찾을 수 있었다.
https://developer.chrome.com/blog/background_tabs/
Chrome 57에서 제공되는 예산 기반 타이머 조절은 타이머 정렬 메커니즘을 더욱 확장하여 백그라운드 타이머 CPU 사용량에 추가 제한을 둡니다. 다음과 같이 작동합니다:
- 각 백그라운드 탭에는 백그라운드에서 타이머를 실행하기 위한 시간 예산(초)이 있습니다.
- 페이지는 백그라운드에서 10초 후에 시간 예산 제한을 받습니다.
- 타이머 작업은 시간 예산이 음수가 아닌 경우에만 실행될 수 있습니다.
- 타이머가 실행된 후에는 실행 시간이 예산에서 차감됩니다.
- 예산은 시간이 지남에 따라 지속적으로 재생성됩니다(현재 초당 0.01초의 속도로 설정됨). Chrome이 제한 동작에 대한 더 많은 데이터를 수집함에 따라 이 예산 재생성 비율이 조정될 수 있습니다.
이 제한에는 여러 가지 자동 예외가 있습니다. - 오디오를 재생하는 애플리케이션은 포그라운드로 간주되며 제한되지 않습니다.
- 시간 초과로 인해 이러한 연결이 닫히는 것을 방지하기 위한 실시간 연결(WebSocket 및 WebRTC)이 있는 애플리케이션. 이러한 경우에도 런타임 타이머는 1초에 한 번 규칙이 적용됩니다.
해결
여러가지 방법이 있을 것 같다.
그 중 webworker라는 방법으로 해결했다.
webworker란 : Web Worker
webworker in react : React에서 WebWorker사용하기